home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / circuits / pcb-1.000 / pcb-1 / pcb-1.3 / dialog.c < prev    next >
C/C++ Source or Header  |  1995-02-27  |  11KB  |  419 lines

  1. /*
  2.  *                            COPYRIGHT
  3.  *
  4.  *  PCB, interactive printed circuit board design
  5.  *  Copyright (C) 1994,1995 Thomas Nau
  6.  *
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License
  18.  *  along with this program; if not, write to the Free Software
  19.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  *  Contact addresses for paper mail and Email:
  22.  *  Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
  23.  *  Thomas.Nau@rz.uni-ulm.de
  24.  *
  25.  */
  26.  
  27. static    char    *rcsid = "$Header: /sda4/users/nau/src/pcb/RCS/dialog.c,v 2.1 1994/09/28 14:26:08 nau Exp $";
  28.  
  29. /* dialog routines
  30.  */
  31.  
  32. #include <stdlib.h>
  33.  
  34. #include "global.h"
  35.  
  36. #include "data.h"
  37. #include "dialog.h"
  38. #include "error.h"
  39. #include "mymem.h"
  40. #include "misc.h"
  41.  
  42. #include <X11/Shell.h>
  43. #include <X11/Xaw/AsciiText.h>
  44. #include <X11/Xaw/Command.h>
  45. #include <X11/Xaw/Dialog.h>
  46. #include <X11/Xaw/Form.h>
  47. #include <X11/Xaw/Label.h>
  48. #include <X11/Xaw/Toggle.h>
  49.  
  50. /* ---------------------------------------------------------------------------
  51.  * include the icon data
  52.  */
  53. #include "icon.data"
  54.  
  55. /* ---------------------------------------------------------------------------
  56.  * some local identifiers
  57.  */
  58. static    int        ReturnCode;        /* used by standard dialogs */
  59.  
  60. /* ---------------------------------------------------------------------------
  61.  * some local prototypes
  62.  */
  63. static    void    CB_OK(Widget, XtPointer, XtPointer);
  64. static    void    CenterDialog(Widget, Boolean, Boolean);
  65. static    void    SendEnterNotify(void);
  66.  
  67. /* ---------------------------------------------------------------------------
  68.  * callback for standard dialog
  69.  * just copies the button-code which is passed as ClientData to a
  70.  * public identifier
  71.  */
  72. static void CB_OK(Widget W, XtPointer ClientData, XtPointer CallData)
  73. {
  74.     ReturnCode = (int) ClientData;
  75. }
  76.  
  77. /* ---------------------------------------------------------------------------
  78.  * centers the widget around the current cursor position
  79.  */
  80. static void CenterDialog(Widget Popup, Boolean CenterX, Boolean CenterY)
  81. {
  82.     Window            root, child;
  83.     int                root_x, root_y,
  84.                     child_x, child_y;
  85.     unsigned int    mask;
  86.     Dimension        width, height;
  87.  
  88.         /* get current pointer position relativ to it's parent */
  89.     XQueryPointer(Dpy, XtWindow(Popup),
  90.         &root, &child,
  91.         &root_x, &root_y,
  92.         &child_x, &child_y,
  93.         &mask);
  94.  
  95.         /* get the dialogs size */
  96.     XtVaGetValues(Popup,
  97.         XtNheight, &height,
  98.         XtNwidth, &width,
  99.         NULL);    
  100.     
  101.         /* make sure position is inside our screen */
  102.     if (CenterX)
  103.         if ((root_x -= (width/2)) < 0)
  104.             root_x = 0;
  105.         else
  106.             if (root_x > WidthOfScreen(XtScreen(Popup)) -width)
  107.                 root_x =  WidthOfScreen(XtScreen(Popup)) -width;
  108.  
  109.     if (CenterY)
  110.         if ((root_y -= (height/2)) < 0)
  111.             root_y = 0;
  112.         else
  113.             if (root_y > HeightOfScreen(XtScreen(Popup)) -height)
  114.                 root_y =  HeightOfScreen(XtScreen(Popup)) -height;
  115.  
  116.     XtVaSetValues(Popup,
  117.         XtNx, root_x,
  118.         XtNy, root_y,
  119.         NULL);
  120. }
  121.  
  122.  
  123. /* ---------------------------------------------------------------------------
  124.  * waits until returncode is differnt from -1
  125.  * see also CB_OK()
  126.  */
  127. int DialogEventLoop(int *Code)
  128. {
  129.     XEvent    event;
  130.  
  131.     for(*Code = -1; *Code == -1;)
  132.     {
  133.         XtAppNextEvent(Context, &event);
  134.         XtDispatchEvent(&event);
  135.     }
  136.     return(*Code);
  137. }
  138.  
  139. /* ---------------------------------------------------------------------------
  140.  * adds the buttons to a dialog
  141.  */
  142. Widget AddButtons(Widget Parent, Widget Top,
  143.     DialogButtonTypePtr Buttons, size_t Count)
  144. {
  145.     int        i;
  146.  
  147.     for (i = 0; i < Count; i++)
  148.     {
  149.             /* skip button if there's no label,
  150.              * used for dialogs without default button
  151.              */
  152.         if (!Buttons[i].Label)
  153.             continue;
  154.         Buttons[i].W  = XtVaCreateManagedWidget(Buttons[i].Name,
  155.             commandWidgetClass,
  156.             Parent,
  157.             XtNlabel, Buttons[i].Label,
  158.             XtNfromHoriz, i ? Buttons[i-1].W : NULL,
  159.             XtNfromVert, Top,
  160.             XtNresizable, True,
  161.             NULL);
  162.  
  163.         XtAddCallback(Buttons[i].W,
  164.             XtNcallback, Buttons[i].Callback, Buttons[i].ClientData);
  165.     }
  166.     return(Buttons[Count-1].W);
  167. }
  168.  
  169. /* ---------------------------------------------------------------------------
  170.  * thanks to Ellen M. Sentovich and Rick L. Spickelm for their hint in
  171.  * xrn
  172.  *
  173.  * creates a dialog box as a child of ... (see arguments)
  174.  */
  175. Widget CreateDialogBox(char *LabelText,
  176.     DialogButtonTypePtr Buttons, size_t Count)
  177. {
  178.     Widget    dialog,
  179.             popup;
  180.  
  181.         /* create the popup shell */
  182.     popup = XtVaCreatePopupShell("popup", transientShellWidgetClass,
  183.         Output.Toplevel,
  184.         XtNinput, True,
  185.         XtNallowShellResize, True,
  186.         NULL);
  187.     dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass,
  188.         popup,
  189.         XtNlabel, LabelText,
  190.         NULL);
  191.  
  192.         /* now we add the buttons and install the accelerators */
  193.     AddButtons(dialog, NULL, Buttons, Count);
  194.     while (Count--)
  195.         XtInstallAccelerators(dialog, Buttons[Count].W);
  196.     return(popup);
  197. }
  198.  
  199. /* ---------------------------------------------------------------------------
  200.  * pops up a dialog
  201.  * saves output window in pixmap
  202.  * first realize the dialog and
  203.  * focus keyboard events from the application to it
  204.  */
  205. void StartDialog(Widget Popup)
  206. {
  207.     SaveOutputWindow();
  208.     XtRealizeWidget(Popup);
  209.     CenterDialog(Popup, True, True);
  210.     XtPopup(Popup, XtGrabExclusive);
  211. }
  212.  
  213. /* ---------------------------------------------------------------------------
  214.  * removes a dialog from screen and from memory
  215.  * pixmap is released by next dialog
  216.  */
  217. void EndDialog(Widget Popup)
  218. {
  219.     XtPopdown(Popup);
  220.     XtDestroyWidget(Popup);
  221.     XFlush(Dpy);
  222.     XSync(Dpy, False);
  223. }
  224.  
  225. /* ---------------------------------------------------------------------------
  226.  * prints out a warning
  227.  */
  228. void MessageDialog(char *MessageText)
  229. {
  230.             Widget                popup;
  231.     static    DialogButtonType    buttons[] = {
  232.         { "defaultButton", "  OK  ", CB_OK, (XtPointer) OK_BUTTON, NULL }};
  233.  
  234.         /* create dialog box */
  235.     popup = CreateDialogBox(MessageText, buttons, ENTRIES(buttons));
  236.     StartDialog(popup);
  237.  
  238.         /* wait for dialog to complete */
  239.     DialogEventLoop(&ReturnCode);
  240.     EndDialog(popup);
  241. }
  242.  
  243. /* ---------------------------------------------------------------------------
  244.  * displays a single line prompt (message)
  245.  */
  246. void MessagePrompt(char *MessageText)
  247. {
  248.         /* set some resources for the input fields */
  249.     if (!MessageText || !*MessageText)
  250.     {
  251.         XUnmapWindow(Dpy, XtWindow(Output.Message));
  252.         XMapWindow(Dpy, XtWindow(Output.StatusLine));
  253.     }
  254.     else
  255.     {
  256.         XtVaSetValues(Output.Message, XtNlabel, EMPTY(MessageText), NULL);
  257.         XUnmapWindow(Dpy, XtWindow(Output.StatusLine));
  258.         XMapWindow(Dpy, XtWindow(Output.Message));
  259.     }
  260. }
  261.  
  262. /* ---------------------------------------------------------------------------
  263.  * called by action ActionFinishInputDialog() to indicate that a user input
  264.  * is finished. The passed parameter signals either OK (True) or Cancel
  265.  */
  266. void FinishInputDialog(Boolean OK)
  267. {
  268.     ReturnCode = OK ? OK_BUTTON : CANCEL_BUTTON;
  269. }
  270.  
  271. /* ---------------------------------------------------------------------------
  272.  * since all my dialogs are modal the X server wont create 'EnterNotify'
  273.  * events during the dialog is popped up. This breaks the crosshair
  274.  * visibility management. Therefore I check if the pointer is inside
  275.  * the output window and generate a 'EnterNotify' event.
  276.  */
  277. static void SendEnterNotify(void)
  278. {
  279.     XEnterWindowEvent    event;
  280.     Window                root, child;
  281.     int                    root_x, root_y,
  282.                         child_x, child_y;
  283.     unsigned int        mask;
  284.  
  285.     if (XQueryPointer(Dpy, Output.OutputWindow, &root, &child,
  286.         &root_x, &root_y, &child_x, &child_y, &mask))
  287.     {
  288.         event.type = EnterNotify;
  289.         event.display = Dpy;
  290.         event.window = Output.OutputWindow;
  291.         event.root = root;
  292.         XSendEvent(Dpy, Output.OutputWindow, True,
  293.             EnterWindowMask, (XEvent *) &event);
  294.     }
  295. }
  296.  
  297. /* ---------------------------------------------------------------------------
  298.  * gets a string from user, memory is allocated for the string,
  299.  * the user is responsible for releasing the allocated memory
  300.  * string might be empty if flag is set
  301.  */
  302. char *GetUserInput(char *MessageText, char *OutputString)
  303. {
  304.     char    *string;
  305.     Widget    inputfield;
  306.  
  307.         /* display single line message */
  308.     MessagePrompt(MessageText);
  309.  
  310.         /* the input field itself */
  311.     inputfield = XtVaCreateManagedWidget("inputField", asciiTextWidgetClass,
  312.         Output.MasterForm,
  313.         XtNresizable, True,
  314.         XtNresize, XawtextResizeWidth,
  315.         XtNstring, EMPTY(OutputString),
  316.         XtNwrap, XawtextWrapNever,
  317.         XtNeditType, XawtextEdit,
  318.         XtNfromHoriz, Output.Message,
  319.         XtNfromVert, Output.Viewport,
  320.         LAYOUT_BOTTOM,
  321.         NULL);
  322.  
  323.         /* set focus to input field, override default translations
  324.          * and install accelerators
  325.          * grap all events --> make widget modal
  326.          */
  327.     XtSetKeyboardFocus(Output.Toplevel, inputfield);
  328.     XtOverrideTranslations(inputfield,
  329.         XtParseTranslationTable(InputTranslations));
  330.     XtInstallAccelerators(inputfield, Output.MasterForm);
  331.     XtAddGrab(inputfield, True, False);
  332.     XtRealizeWidget(inputfield);
  333.  
  334.         /* wait for input to complete and allocate memory if necessary */
  335.     if (DialogEventLoop(&ReturnCode) == OK_BUTTON)
  336.     {
  337.             /* strip white space and return string */
  338.         XtVaGetValues(inputfield, XtNstring, &string, NULL);
  339.         string = StripWhiteSpaceAndDup(string);
  340.     }
  341.     else
  342.         string = NULL;
  343.  
  344.         /* restore normal outfit */
  345.     XtRemoveGrab(inputfield);
  346.     XtDestroyWidget(inputfield);
  347.     MessagePrompt(NULL);
  348.  
  349.         /* force an 'EnterNotify' event if the pointer has moved
  350.          * into the output area
  351.          */
  352.     SendEnterNotify();
  353.     XSync(Dpy, False);
  354.     return(string);
  355. }
  356.  
  357. /* ---------------------------------------------------------------------------
  358.  * pops up and 'About' dialog
  359.  */
  360. void AboutDialog(void)
  361. {
  362.             Widget                popup,
  363.                                 dialog;
  364.             Pixmap                icon = BadAlloc;
  365.     static    DialogButtonType    button =
  366.         { "defaultButton", "  OK  ", CB_OK, (XtPointer) OK_BUTTON, NULL };
  367.  
  368.         /* create dialog box */
  369.     popup = CreateDialogBox(
  370.         "This is PCB, an interactive\n"
  371.         "printed circuit board editor\n"
  372.         "version "RELEASE"\n\n"
  373.         "by Thomas Nau (c) 1994\n\n"
  374.         "If you have problems, hints or\n"
  375.         "suggestions, send mail to:\n"
  376.         "Thomas.Nau@rz.uni-ulm.de\n\n",
  377.         &button, 1);
  378.     if ((dialog = XtNameToWidget(popup, "dialog")) != NULL)
  379.     {
  380.         Screen    *screen = XtScreen(Output.Toplevel);
  381.  
  382.         if ((icon = XCreatePixmapFromBitmapData(Dpy,
  383.             XtWindow(Output.Toplevel), icon_bits, icon_width, icon_height,
  384.             BlackPixelOfScreen(screen), WhitePixelOfScreen(screen),
  385.             DefaultDepthOfScreen(screen))) != BadAlloc)
  386.         {
  387.             XtVaSetValues(dialog, XtNicon, icon, NULL);
  388.         }
  389.     }    
  390.             
  391.     StartDialog(popup);
  392.  
  393.         /* wait for dialog to complete */
  394.     DialogEventLoop(&ReturnCode);
  395.     EndDialog(popup);
  396.     if (icon != BadAlloc)
  397.         XFreePixmap(Dpy, icon);
  398. }
  399.  
  400. /* ----------------------------------------------------------------------
  401.  * confirmation dialog
  402.  */
  403. Boolean ConfirmDialog(char *MessageText)
  404. {
  405.             Widget                popup;
  406.     static    DialogButtonType    buttons[] = {
  407.         { "defaultButton", "No/Cancel", CB_OK, (XtPointer) CANCEL_BUTTON, NULL},
  408.         { "okButton", "   OK   ", CB_OK, (XtPointer) OK_BUTTON, NULL}};
  409.  
  410.         /* create dialog box */
  411.     popup = CreateDialogBox(MessageText, buttons, ENTRIES(buttons));
  412.     StartDialog(popup);
  413.  
  414.         /* wait for dialog to complete */
  415.     DialogEventLoop(&ReturnCode);
  416.     EndDialog(popup);
  417.     return(ReturnCode == OK_BUTTON);
  418. }
  419.